home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
417_02
/
unzip.tz
/
unzip
/
unz50p1
/
match.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-10
|
19KB
|
564 lines
/*---------------------------------------------------------------------------
match.c
The match() routine recursively compares a string to a "pattern" (regular
expression), returning TRUE if a match is found or FALSE if not. This
version is specifically for use with unzip.c: as did the previous match()
from SEA, it leaves the case (upper, lower, or mixed) of the string alone,
but converts any uppercase characters in the pattern to lowercase if indi-
cated by the global var pInfo->lcflag (which is to say, string is assumed
to have been converted to lowercase already, if such was necessary).
---------------------------------------------------------------------------*/
#ifdef ZIPINFO
# undef ZIPINFO /* make certain there is only one version of match.o */
#endif /* ZIPINFO */
#include "unzip.h"
static int matche __((register char *p, register char *t));
static int matche_after_star __((register char *p, register char *t));
/* #include "filmatch.h": */
#ifndef BOOLEAN
# define BOOLEAN short int /* v1.2 made it short */
#endif
/* match defines */
#define MATCH_PATTERN 6 /* bad pattern */
#define MATCH_LITERAL 5 /* match failure on literal match */
#define MATCH_RANGE 4 /* match failure on [..] construct */
#define MATCH_ABORT 3 /* premature end of text string */
#define MATCH_END 2 /* premature end of pattern string */
#define MATCH_VALID 1 /* valid match */
/* pattern defines */
#define PATTERN_VALID 0 /* valid pattern */
#define PATTERN_ESC -1 /* literal escape at end of pattern */
#define PATTERN_RANGE -2 /* malformed range in [..] construct */
#define PATTERN_CLOSE -3 /* no end bracket in [..] construct */
#define PATTERN_EMPTY -4 /* [..] contstruct is empty */
/*----------------------------------------------------------------------------
*
* Match the pattern PATTERN against the string TEXT;
*
* match() returns TRUE if pattern matches, FALSE otherwise.
* matche() returns MATCH_VALID if pattern matches, or an errorcode
* as follows otherwise:
*
* MATCH_PATTERN - bad pattern
* MATCH_RANGE - match failure on [..] construct
* MATCH_ABORT - premature end of text string
* MATCH_END - premature end of pattern string
* MATCH_VALID - valid match
*
*
* A match means the entire string TEXT is used up in matching.
*
* In the pattern string:
* `*' matches any sequence of characters (zero or more)
* `?' matches any character
* [SET] matches any character in the specified set,
* [!SET] or [^SET] matches any character not in the specified set.
*
* A set is composed of characters or ranges; a range looks like
* character hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the
* minimal set of characters allowed in the [..] pattern construct.
* Other characters are allowed (ie. 8 bit characters) if your system
* will support them.
*
* To suppress the special syntactic significance of any of `[]*?!^-\',
* in a [..] construct and match the character exactly, precede it
* with a `\'.
*
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
*
* Match the pattern PATTERN against the string TEXT;
*
* returns MATCH_VALID if pattern matches, or an errorcode as follows
* otherwise:
*
* MATCH_PATTERN - bad pattern
* MATCH_RANGE - match failure on [..] construct
* MATCH_ABORT - premature end of text string
* MATCH_END - premature end of pattern string
* MATCH_VALID - valid match
*
*
* A match means the entire string TEXT is used up in matching.
*
* In the pattern string:
* `*' matches any sequence of characters (zero or more)
* `?' matches any character
* [SET] matches any character in the specified set,
* [!SET] or [^SET] matches any character not in the specified set.
* \ is allowed within a set to escape a character like ']' or '-'
*
* A set is composed of characters or ranges; a range looks like
* character hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the
* minimal set of characters allowed in the [..] pattern construct.
* Other characters are allowed (ie. 8 bit characters) if your system
* will support them.
*
* To suppress the special syntactic significance of any of `[]*?!^-\',
* within a [..] construct and match the character exactly, precede it
* with a `\'.
*
----------------------------------------------------------------------------*/
static int matche(p, t)
register char *p;
register char *t;
{
register char range_start, range_end; /* start and end in range */
BOOLEAN invert; /* is this [..] or [!..] */
BOOLEAN member_match; /* have I matched the [..] construct? */
BOOLEAN loop; /* should I terminate? */
for (; *p; p++, t++) {
/* if this is the end of the text then this is the end of the match */
if (!*t)
return ((*p == '*') && (*++p == '\0'))? MATCH_VALID : MATCH_ABORT;
/* determine and react to pattern type */
switch (*p) {
/* single any character match */
case '?':
break;
/* multiple any character match */
case '*':
return matche_after_star (p, t);
/* [..] construct, single member/exclusion character match */
case '[': {
/* move to beginning of range */
p++;
/* check if this is a member match or exclusion match */
invert = FALSE;
if ((*p == '!') || (*p == '^')) {
invert = TRUE;
p++;
}
/* if closing bracket here or at range start then we have a
malformed pattern */
if (*p == ']')
return MATCH_PATTERN;
member_match = FALSE;
loop = TRUE;
while (loop) {
/* if end of construct then loop is done */
if (*p == ']') {
loop = FALSE;
continue;
}
/* matching a '!', '^', '-', '\' or a ']' */
if (*p == '\\')
range_start = range_end = *++p;
else
range_start = range_end = *p;
/* if end of pattern then bad pattern (Missing ']') */
if (!*p)
return MATCH_PATTERN;
/* check for range bar */
if (*++p == '-') {
/* get the range end */
range_end = *++p;
/* if end of pattern or construct then bad pattern */
if ((range_end == '\0') || (range_end == ']'))
return MATCH_PATTERN;
/* special character range end */
if (range_end == '\\') {
range_end = *++p;
/* if end of text then we have a bad pattern */
if (!range_end)
return MATCH_PATTERN;
}
/* move just beyond this range */
p++;
}
/* if the text character is in range then match found.
* make sure the range letters have the proper
* relationship to one another before comparison
*/
if (range_start < range_end) {
if ((*t >= range_start) && (*t <= range_end)) {
member_match = TRUE;
loop = FALSE;
}
} else {
if ((*t >= range_end) && (*t <= range_start)) {